#include "highgui.h"
#include "cv.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <FL/Fl_File_Chooser.H>
#include "Utils.hpp"
#include "Parabola.hpp"

using namespace std;

void mouseCallback(int event, int x, int y, int flags, void* param);
CvRect box;
bool drawing_box = false;
bool drawGrid = true;
bool deformingPic = false;
bool deformPicture = false;
int numOfCols,numOfRows, interpolationMethod;
vector<int> xs;


int main( int argc, char** argv ) {

	//opens a file chooser windows
	Fl_File_Chooser fileChooser(".","*.jpg",0,"File Chooser");
	fileChooser.show();
	while( fileChooser.shown() ) { Fl::wait(); }

	IplImage* img = cvLoadImage(fileChooser.value(),1);
	//makes the file chooser windows disappear
	fileChooser.rescan();
	fileChooser.hide();


	cvNamedWindow("Original Picture", CV_WINDOW_AUTOSIZE);
	cvShowImage( "Original Picture", img );

	fileChooser.rescan();

	numOfRows = 1; numOfCols = 1;
	//keeps asking the user for number of rows and columns until they both are even
	while (numOfRows%2 !=0 || numOfCols%2 !=0) {
		cout << "How many rows would you like the grid to contain ? (only even number)" << endl;
		cin >> numOfRows;
		cout << "How many columns would you like the grid to contain ? (only even number)" << endl;
		cin >> numOfCols ;
	}

	cout << "What interpolation method would you like to use ? \n"
			"1 - Nearest\n"
			"2 - BiLinear\n"
			"3 - BiCubic" << endl;
	cin >> interpolationMethod;

	box = cvRect(-1,-1,0,0);
    IplImage* temp = cvCloneImage( img );
    cvNamedWindow( "Original Picture" );

    cvSetMouseCallback("Original Picture",mouseCallback,(void*) img);

    while( 1 ) {
      cvCopyImage( img, temp );
      if( drawing_box ) {
    	  Utils::draw_grid(temp,numOfRows,numOfCols,box);
      }
      cvShowImage( "Original Picture", temp );
      if (cvWaitKey( 15 )==27) {
    	  break;
      }
    }

    cvReleaseImage( &img );

    cvReleaseImage( &temp );
    cvDestroyWindow( "Original Picture" );
}


void mouseCallback (int event, int x, int y, int flags, void* param) {
	IplImage* image = (IplImage*) param;

	if (drawGrid) {

		switch( event ) {
		  case CV_EVENT_MOUSEMOVE: {
			if( drawing_box ) {
			  box.width = x-box.x;
			  box.height = y-box.y;
			}
		  }
		  break;
		  case CV_EVENT_LBUTTONDOWN: {
			drawing_box = true;
			box = cvRect(x, y, 0, 0);
		  }
		  break;
		  case CV_EVENT_LBUTTONUP: {
			drawing_box = false;
			if(box.width<0) {
			  box.x+=box.width;
			  box.width *=-1;
			}
			if(box.height<0) {
			  box.y+=box.height;
			  box.height*=-1;
			}
			Utils::draw_grid(image,numOfRows,numOfCols,box);
			drawGrid = false;
			deformPicture = true;
		  }
		  break;
	   }
	} else if (deformPicture && box.x<=x && x<=box.x+box.width) {

		switch( event ) {
		  case CV_EVENT_MOUSEMOVE: {
			if( deformingPic ) {
				IplImage* temp = cvCloneImage( image );
				Utils::deformPic(image,temp,box,abs(xs.at(0) - xs.at(1)), xs.at(0) < xs.at(1) ? true : false, interpolationMethod);
				cvNamedWindow("Deforming Image", CV_WINDOW_AUTOSIZE);
				cvShowImage( "Deforming Image", temp );
                cvReleaseImage( &temp );
				xs.pop_back();
				xs.push_back(x);
			}
		  }
		  break;
		  case CV_EVENT_LBUTTONDOWN: {
			deformingPic = true;
			xs.push_back(x);
			xs.push_back(x);
		  }
		  break;
		  case CV_EVENT_LBUTTONUP: {
			deformingPic = false;
			deformPicture = false;
			cout << "d: " << abs(xs.at(0) - xs.at(1)) << endl;

		  }
		  break;
	   }
	}
}
